<?php
/**
 * The Router class
 */
class LtRouter
{
	public $configHandle;
	public $routingTable;
	public $module;
	public $action;

	public function __construct()
	{
		if (! $this->configHandle instanceof LtConfig)
		{
			$this->configHandle = LtObjectUtil::singleton("LtConfig");
		}
	}

	public function init()
	{
		$this->routingTable = $this->configHandle->get("router.routing_table");
		if (empty($this->routingTable))
		{
			$this->routingTable = array('pattern' => ":module/:action/*",
				'default' => array('module' => 'default', 'action' => 'index'),
				'reqs' => array('module' => '[a-zA-Z0-9\.\-_]+',
					'action' => '[a-zA-Z0-9\.\-_]+'
					),
				'varprefix' => ':',
				'delimiter' => '/',
				'postfix' => '',
				'protocol' => 'PATH_INFO', // REWRITE STANDARD
				);
		}
		//url简化
		$this->shortCut 	= $this->configHandle->get("router.short_cut");
		if (empty($this->shortCut))
		{
			$this->shortCut	= array();
		}
		
		$delimiter = $this->routingTable['delimiter'];
		$postfix = $this->routingTable['postfix'];
		$protocol = strtoupper($this->routingTable['protocol']);
		$module = '';
		$action = '';
		$params = array(); 
		
		if (isset($_SERVER['REQUEST_URI']))
		{
			if ('REWRITE' == $protocol)
			{
				if (0 == strcmp($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
				{
					$params	= array();
				}
				else
				{
					if(strpos($_SERVER['REQUEST_URI'],$_SERVER['SCRIPT_NAME'])===0)
					{
						$url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
					}
					else
					{
						$url = substr($_SERVER['REQUEST_URI'], strlen(pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_DIRNAME)));
					}
					$url = $this->rtrim($url, "$postfix");
					$url = explode($delimiter, trim($url, "/"));
					$params = $this->matchingRoutingTable($url);
				}
			}
			else if ('PATH_INFO' == $protocol)
			{
				$url = substr($_SERVER['REQUEST_URI'], strlen($_SERVER['SCRIPT_NAME']));
				$url = $this->rtrim($url, "$postfix");
				$url = explode($delimiter, trim($url, "/"));
				$params = $this->matchingRoutingTable($url);
			}
			else
			{
				foreach($_GET as $k=>$v)
				{
					$_GET[$k] = rawurldecode($v);
				}
				$params = $_GET;
			}
		}
		else
		{
			foreach($_GET as $k=>$v)
			{
				$_GET[$k] = rawurldecode($v);
			}
			$params = $_GET;
		}
		
		if(!array_key_exists('module', $params))
		{
			$params['module'] = $this->routingTable['default']['module'];
		}
		if(!array_key_exists('action', $params))
		{
			$params['action'] = $this->routingTable['default']['action'];
		}
		
		$module = $params['module'];
		$action = $params['action'];
		
		// 如果$_GET中不存在配置的变量则添加
		foreach($params as $k => $v)
		{
			!isset($_GET[$k]) && $_GET[$k] = $v;
		}
		
		$this->module = $module;
		$this->action = $action;
	}

	/**
	 * url 匹配路由表
	 * 
	 * @param  $ [string|array] $url
	 * @return 
	 */
	public function matchingRoutingTable($url)
	{
		$ret = array();
		$reqs = $this->routingTable['reqs'];
		$delimiter = $this->routingTable['delimiter'];
		$varprefix = $this->routingTable['varprefix'];
		$postfix = $this->routingTable['postfix'];
		$pattern = explode($delimiter, trim($this->routingTable['pattern'], $delimiter));
		
		/**
		 * 预处理url
		 */
		if (is_string($url))
		{
			$url = $this->rtrim($url, $postfix); //忽略后缀
			$url = explode($delimiter, trim($url, $delimiter));
		}
		
		foreach($this->shortCut as $k=>$v)
		{
			if($v!='' && $url[0]==$v)
			{
				array_shift($url);
				$url	= array_merge(explode($delimiter, $k),$url);
				break;
			}
		}
		
		if(strpos($url[0],'?')===0)
		{
			//?开头的，直接返回空
			return $ret;
		}
		
		foreach($pattern as $k => $v)
		{
			if ($v[0] == $varprefix)
			{ 
				// 变量
				$varname = substr($v, 1); 
				// 匹配变量
				if (isset($url[$k]))
				{
					if (isset($reqs[$varname]))
					{
						$regex = "/^{$reqs[$varname]}\$/i";
						if (preg_match($regex, $url[$k]))
						{
							$ret[$varname] = $url[$k];
						}
					}
				}
			}
			else if ($v[0] == '*')
			{ 
				// 通配符
				$pos = $k;
				while (isset($url[$pos]) && isset($url[$pos + 1]))
				{
					$ret[$url[$pos ++]] = rawurldecode($url[$pos]);
					$pos++;
				}
			}
			else
			{ 
				// 静态
			}
		}
		
		//module和action要么两个都解析出来，要么都不解析出来，如果只有一个有，说明解析不正确
		if(!array_key_exists('module', $ret) && array_key_exists('action', $ret))
		{
			header("HTTP/1.0 404 Not Found");
			exit;
		}
		if(array_key_exists('module', $ret) && !array_key_exists('action', $ret))
		{
			header("HTTP/1.0 404 Not Found");
			exit;
		}
		
		return $ret;
	}
	
	private function rtrim($str,$find)
	{
		if($find!='' && strrpos($str,$find)!==false)
		{
			$str = substr($str, 0, strrpos($str,$find));
		}
		return $str;
	}
}
